home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 008a / xmsif140.zip / TESTUTIL.C < prev    next >
C/C++ Source or Header  |  1991-11-15  |  36KB  |  769 lines

  1. /***************************************************************************
  2. *   TESTUTIL.C                                                             *
  3. *   MODULE:  TESTUTIL                                                      *
  4. *   OS:      DOS                                                           *
  5. *   VERSION: 1.0                                                           *
  6. *   DATE:    11/15/91                                                      *
  7. *                                                                          *
  8. *   Copyright (c) 1991 James W. Birdsall. All Rights Reserved.             *
  9. *                                                                          *
  10. *   Requires testutil.h to compile.                                        *
  11. *   Compiles under Borland C++ 2.0, TC 2.0, or MSC 6.00A.                  *
  12. *                                                                          *
  13. *   This file contains various utility functions used to fill and check    *
  14. *   blocks of memory and perform other basic services. Many are coded in   *
  15. *   in-line assembly language to improve speed. The in-line assembly is    *
  16. *   compatible with both Turbo/Borland C[++] and MSC 6.00A. If your        *
  17. *   compiler does not support in-line assembly, or your compiler requires  *
  18. *   an external assembler which you do not have, or you simply do not wish *
  19. *   to use the in-line assembly code, the functions also contain C code    *
  20. *   versions. The C code versions are the default; in order to use the     *
  21. *   in-line assembly, you must define the symbol INLINE_ASM when           *
  22. *   compiling.                                                             *
  23. *                                                                          *
  24. ***************************************************************************/
  25.  
  26. /*
  27. ** system includes <>
  28. */
  29.  
  30. #include <string.h>
  31. #include <dos.h>
  32.  
  33.  
  34. /*
  35. ** custom includes ""
  36. */
  37.  
  38. #include "testutil.h"
  39.  
  40.  
  41. /*
  42. ** local #defines
  43. */
  44.  
  45. /*
  46. ** misc: copyright strings, version macros, etc.
  47. */
  48.  
  49. /*
  50. ** typedefs
  51. */
  52.  
  53. /*
  54. ** global variables
  55. */
  56.  
  57. /*
  58. ** static globals
  59. */
  60.  
  61. /*
  62. ** function prototypes
  63. */
  64.  
  65. /*
  66. ** functions
  67. */
  68.  
  69. /***************************************************************************
  70. *   FUNCTION: FARMEMCHECK                                                  *
  71. *                                                                          *
  72. *   DESCRIPTION:                                                           *
  73. *                                                                          *
  74. *       This function scans a block of memory looking for bytes which do   *
  75. *       not match checkchar.                                               *
  76. *                                                                          *
  77. *   ENTRY:                                                                 *
  78. *                                                                          *
  79. *       buffer    - pointer to block of memory to scan                     *
  80. *       len       - length of block                                        *
  81. *       checkchar - value which should be matched                          *
  82. *                                                                          *
  83. *   EXIT:                                                                  *
  84. *                                                                          *
  85. *       Returns 0 if all bytes match, nonzero if mismatch found.           *
  86. *                                                                          *
  87. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  88. *                                                                          *
  89. ***************************************************************************/
  90. int farmemcheck(unsigned char far *buffer, unsigned int len,
  91.                                                        unsigned char checkchar)
  92. {
  93.     int retval = 0;
  94.     unsigned char huge *temp;
  95.  
  96.     /* normalize far pointer and turn into huge pointer */
  97.     temp = normptr(buffer);
  98.  
  99. #ifdef INLINE_ASM
  100.     ASM  push     bx                    /* preserve registers           */
  101.     ASM  push     cx
  102.     ASM  push     si
  103.     ASM  push     ds
  104.     ASM  lds      si, [temp]            /* load pointer into DS:SI      */
  105.     ASM  mov      cx, [len]             /* load length into CX          */
  106.     ASM  mov      bl, [checkchar]       /* load match value into BX     */
  107. looptop:
  108.     ASM  lodsb                          /* load next byte into AL       */
  109.     ASM  cmp      al, bl                /* test against BL              */
  110.     ASM  jne      nomatch               /* if not equal, exit loop      */
  111.     ASM  loop     looptop               /* otherwise loop               */
  112.     ASM  jmp      match
  113. nomatch:
  114.     ASM  mov      WORD PTR [retval], 1  /* return nonzero on mismatch   */
  115. match:
  116.     ASM  pop      ds                    /* restore register values      */
  117.     ASM  pop      si
  118.     ASM  pop      cx
  119.     ASM  pop      bx
  120. #else
  121.     for (; len; len--, temp++)          /* do the same thing in C       */
  122.     {
  123.         if (*temp != checkchar)
  124.         {
  125.             retval = 1;
  126.             break;
  127.         }
  128.     }
  129. #endif
  130.  
  131.     return retval;
  132. } /* end of farmemcheck() */
  133.  
  134.  
  135. /***************************************************************************
  136. *   FUNCTION: LFARMEMCHECK                                                 *
  137. *                                                                          *
  138. *   DESCRIPTION:                                                           *
  139. *                                                                          *
  140. *       This function scans a block of memory longer than 64K looking for  *
  141. *       bytes which do not match checkchar.                                *
  142. *                                                                          *
  143. *   ENTRY:                                                                 *
  144. *                                                                          *
  145. *       buffer    - pointer to block of memory to scan                     *
  146. *       len       - length of block                                        *
  147. *       checkchar - value which should be matched                          *
  148. *                                                                          *
  149. *   EXIT:                                                                  *
  150. *                                                                          *
  151. *       Returns 0 if all bytes match, nonzero if mismatch found.           *
  152. *                                                                          *
  153. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  154. *                                                                          *
  155. ***************************************************************************/
  156. int lfarmemcheck(unsigned char far *buffer, unsigned long len,
  157.                                                        unsigned char checkchar)
  158. {
  159.     int retval;
  160.     unsigned int copylen;
  161.     unsigned char huge *temp;
  162.  
  163.     /* normalize far pointer and turn into huge pointer */
  164.     temp = normptr(buffer);
  165.  
  166.     while (len > 0L)
  167.     {
  168.         copylen = ((len > 65000L) ? 65000U : (unsigned int) len);
  169.         if ((retval = farmemcheck((void far *) temp, copylen, checkchar)) != 0)
  170.         {
  171.             return retval;
  172.         }
  173.         temp = normptr((unsigned char far *)(temp + copylen));
  174.         len -= copylen;
  175.     }
  176.  
  177.     return retval;
  178. } /* end of lfarmemcheck() */
  179.  
  180.  
  181. /***************************************************************************
  182. *   FUNCTION: LFMEMCMP                                                     *
  183. *                                                                          *
  184. *   DESCRIPTION:                                                           *
  185. *                                                                          *
  186. *       Compares two regions of memory longer than 64K.                    *
  187. *                                                                          *
  188. *   ENTRY:                                                                 *
  189. *                                                                          *
  190. *       buf1 - pointer to first region                                     *
  191. *       buf2 - pointer to second region                                    *
  192. *       n    - length of regions                                           *
  193. *                                                                          *
  194. *   EXIT:                                                                  *
  195. *                                                                          *
  196. *       Returns 0 on match, negative if mismatch byte in buf1 is less than *
  197. *       corresponding byte in buf2, positive if vice versa.                *
  198. *                                                                          *
  199. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  200. *                                                                          *
  201. ***************************************************************************/
  202. int LFMEMCMP(void far *buf1, void far *buf2, unsigned long n)
  203. {
  204.     unsigned char huge *temp1, huge *temp2;
  205.     int retval = 0;
  206.     unsigned int cmplen;
  207.  
  208.     /* normalize far pointers and turn into huge pointers */
  209.     temp1 = normptr(buf1);
  210.     temp2 = normptr(buf2);
  211.  
  212.     while (n > 0L)
  213.     {
  214.         cmplen = ((n > 65000L) ? 65000U : (unsigned int) n);
  215.         retval = FMEMCMP((void far *) temp1, (void far *) temp2, cmplen);
  216.         if (retval != 0)
  217.         {
  218.             return retval;
  219.         }
  220.         temp1 = normptr((unsigned char far *)(temp1 + cmplen));
  221.         temp2 = normptr((unsigned char far *)(temp2 + cmplen));
  222.         n -= cmplen;
  223.     }
  224.  
  225.     return retval;
  226. } /* end of LFMEMCMP() */
  227.  
  228.  
  229. /***************************************************************************
  230. *   FUNCTION: LFMEMSET                                                     *
  231. *                                                                          *
  232. *   DESCRIPTION:                                                           *
  233. *                                                                          *
  234. *       Sets a region of memory longer than 64K to a particular value.     *
  235. *                                                                          *
  236. *   ENTRY:                                                                 *
  237. *                                                                          *
  238. *       s - pointer to region of memory                                    *
  239. *       c - byte value to set memory to                                    *
  240. *       n - length of region                                               *
  241. *                                                                          *
  242. *   EXIT:                                                                  *
  243. *                                                                          *
  244. *       Void.                                                              *
  245. *                                                                          *
  246. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  247. *                                                                          *
  248. ***************************************************************************/
  249. void LFMEMSET(void far *s, int c, unsigned long n)
  250. {
  251.     unsigned char huge *temp;
  252.     unsigned int fill_len;
  253.  
  254.     /* normalize far pointer and turn into huge pointer */
  255.     temp = normptr(s);
  256.  
  257.     while (n > 0L)
  258.     {
  259.         fill_len = ((n > 65000L) ? 65000U : (unsigned int) n);
  260.         FMEMSET((void far *) temp, c, fill_len);
  261.         temp = normptr((unsigned char far *)(temp + fill_len));
  262.         n -= fill_len;
  263.     }
  264.  
  265.     return;
  266. } /* end of LFMEMSET() */
  267.  
  268.  
  269. /***************************************************************************
  270. *   FUNCTION: FARINCWORDFILL                                               *
  271. *                                                                          *
  272. *   DESCRIPTION:                                                           *
  273. *                                                                          *
  274. *       Fill a region of memory with incrementing word (16 bit) values.    *
  275. *       Always starts at 0 value.                                          *
  276. *                                                                          *
  277. *   ENTRY:                                                                 *
  278. *                                                                          *
  279. *       buffer - pointer to block of memory                                *
  280. *       len    - length of block, must be even                             *
  281. *                                                                          *
  282. *   EXIT:                                                                  *
  283. *                                                                          *
  284. *       Void.                                                              *
  285. *                                                                          *
  286. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  287. *                                                                          *
  288. ***************************************************************************/
  289. void farincwordfill(unsigned char far *buffer, unsigned int len,
  290.                                                             unsigned int start)
  291. {
  292.     unsigned char huge *temp;
  293. #ifndef INLINE_ASM
  294.     int loop;
  295.     unsigned int huge *filler;
  296.     unsigned int value;
  297. #endif
  298.  
  299.     /* turn length in bytes into length in words, convert pointer */
  300.     len /= 2;
  301.     temp = normptr(buffer);
  302.  
  303. #ifdef INLINE_ASM
  304.     ASM  push     ax                    /* preserve registers           */
  305.     ASM  push     cx
  306.     ASM  push     di
  307.     ASM  push     es
  308.     ASM  les      di, [temp]            /* load pointer into ES:DI      */
  309.     ASM  mov      cx, [len]             /* load length into CX          */
  310.     ASM  mov      ax, [start]           /* load starting value into AX  */
  311. loop2top:
  312.     ASM  stosw                          /* store AX in memory, DI += 2  */
  313.     ASM  inc      ax                    /* increment AX                 */
  314.     ASM  loop     loop2top              /* loop                         */
  315.     ASM  pop      es                    /* restore register values      */
  316.     ASM  pop      di
  317.     ASM  pop      cx
  318.     ASM  pop      ax
  319. #else
  320.     /* do the same thing in C */
  321.     for (loop = 0, filler = (unsigned int huge *) temp, value = start;
  322.          loop < len;
  323.          loop++, value++)
  324.     {
  325.         filler[loop] = value;
  326.     }
  327. #endif
  328.  
  329.     return;
  330. } /* end of farincwordfill() */
  331.  
  332.  
  333. /***************************************************************************
  334. *   FUNCTION: LFARINCWORDFILL                                              *
  335. *                                                                          *
  336. *   DESCRIPTION:                                                           *
  337. *                                                                          *
  338. *       This function fills a block of memory longer than 64K with         *
  339. *       incrementing word values.                                          *
  340. *                                                                          *
  341. *   ENTRY:                                                                 *
  342. *                                                                          *
  343. *       buffer - pointer to block of memory to fill                        *
  344. *       len    - length of block                                           *
  345. *       start  - value at which incrementing words start                   *
  346. *                                                                          *
  347. *   EXIT:                                                                  *
  348. *                                                                          *
  349. *       Void.                                                              *
  350. *                                                                          *
  351. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  352. *                                                                          *
  353. ***************************************************************************/
  354. void lfarincwordfill(unsigned char far *buffer, unsigned long len,
  355.                                                             unsigned int start)
  356. {
  357.     unsigned int fill_len;
  358.     unsigned char huge *temp;
  359.     unsigned int value;
  360.  
  361.     /* normalize far pointer and turn into huge pointer */
  362.     temp = normptr(buffer);
  363.  
  364.     value = start;
  365.  
  366.     while (len > 0L)
  367.     {
  368.         fill_len = ((len > 65000L) ? 65000U : (unsigned int) len);
  369.         farincwordfill((void far *) temp, fill_len, value);
  370.         temp = normptr((unsigned char far *)(temp + fill_len));
  371.         len -= fill_len;
  372.         value += (fill_len / 2);
  373.     }
  374.  
  375.     return;
  376. } /* end of lfarincwordfill() */
  377.  
  378.  
  379. /***************************************************************************
  380. *   FUNCTION: FARINCWORDCHECK                                              *
  381. *                                                                          *
  382. *   DESCRIPTION:                                                           *
  383. *                                                                          *
  384. *       Scans a block of memory to make sure contents are incrementing     *
  385. *       word values.                                                       *
  386. *                                                                          *
  387. *   ENTRY:                                                                 *
  388. *                                                                          *
  389. *       buffer - pointer to block of memory                                *
  390. *       len    - length of block of memory, must be even                   *
  391. *                                                                          *
  392. *   EXIT:                                                                  *
  393. *                                                                          *
  394. *       Returns 0 if contents are OK, nonzero if mismatch found.           *
  395. *                                                                          *
  396. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  397. *                                                                          *
  398. ***************************************************************************/
  399. int farincwordcheck(unsigned char far *buffer, unsigned int len,
  400.                                                             unsigned int start)
  401. {
  402.     int retval = 0;
  403.     unsigned char huge *temp;
  404. #ifndef INLINE_ASM
  405.     int loop;
  406.     unsigned int huge *filler;
  407.     unsigned int value;
  408. #endif
  409.  
  410.     /* convert length in bytes to length in words, convert pointer */
  411.     len /= 2;
  412.     temp = normptr(buffer);
  413.  
  414. #ifdef INLINE_ASM
  415.     ASM  push     ax                    /* preserve register values     */
  416.     ASM  push     bx
  417.     ASM  push     cx
  418.     ASM  push     si
  419.     ASM  push     ds
  420.     ASM  lds      si, [temp]            /* load pointer into DS:SI      */
  421.     ASM  mov      cx, [len]             /* load length into CX          */
  422.     ASM  mov      bx, [start]           /* load starting value into BX  */
  423.     ASM  dec      bx                    /* decrement BX, prep for loop  */
  424. loop3top:
  425.     ASM  inc      bx                    /* increment BX to next value   */
  426.     ASM  lodsw                          /* load next word into AX       */
  427.     ASM  cmp      ax, bx                /* compare word in AX and BX    */
  428.     ASM  loope    loop3top              /* loop while words are equal   */
  429.     ASM  je       done                  /* exited loop -- if last cmp   */
  430.                                         /* was equal, jump to end, else */
  431.     ASM  mov      WORD PTR [retval], 1  /* mismatch, set nonzero retval */
  432. done:
  433.     ASM  pop      ds                    /* restore register values      */
  434.     ASM  pop      si
  435.     ASM  pop      cx
  436.     ASM  pop      bx
  437.     ASM  pop      ax
  438. #else
  439.     /* do the same thing in C */
  440.     for (loop = 0, filler = (unsigned int huge *) temp, value = start;
  441.          loop < len;
  442.          loop++, value++)
  443.     {
  444.         if (filler[loop] != value)
  445.         {
  446.             retval = 1;
  447.             break;
  448.         }
  449.     }
  450. #endif
  451.  
  452.     return retval;
  453. } /* end of farincwordcheck() */
  454.  
  455.  
  456. /***************************************************************************
  457. *   FUNCTION: LFARINCWORDCHECK                                             *
  458. *                                                                          *
  459. *   DESCRIPTION:                                                           *
  460. *                                                                          *
  461. *       This function checks a block of memory longer than 64K for         *
  462. *       incrementing word values.                                          *
  463. *                                                                          *
  464. *   ENTRY:                                                                 *
  465. *                                                                          *
  466. *       buffer - pointer to block of memory to check                       *
  467. *       len    - length of block                                           *
  468. *       start  - value at which incrementing words start                   *
  469. *                                                                          *
  470. *   EXIT:                                                                  *
  471. *                                                                          *
  472. *       Returns 0 if contents are OK, nonzero if mismatch found.           *
  473. *                                                                          *
  474. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  475. *                                                                          *
  476. ***************************************************************************/
  477. int lfarincwordcheck(unsigned char far *buffer, unsigned long len,
  478.                                                             unsigned int start)
  479. {
  480.     int retval;
  481.     unsigned int checklen;
  482.     unsigned char huge *temp;
  483.     unsigned int value;
  484.  
  485.     /* normalize far pointer and turn into huge pointer */
  486.     temp = normptr(buffer);
  487.  
  488.     value = start;
  489.  
  490.     while (len > 0L)
  491.     {
  492.         checklen = ((len > 65000L) ? 65000U : (unsigned int) len);
  493.         if ((retval = farincwordcheck((void far *) temp, checklen, value)) != 0)
  494.         {
  495.             return retval;
  496.         }
  497.         temp = normptr((unsigned char far *)(temp + checklen));
  498.         len -= checklen;
  499.         value += (checklen / 2);
  500.     }
  501.  
  502.     return retval;
  503. } /* end of lfarincwordcheck() */
  504.  
  505.  
  506. /***************************************************************************
  507. *   FUNCTION: GET_TICK                                                     *
  508. *                                                                          *
  509. *   DESCRIPTION:                                                           *
  510. *                                                                          *
  511. *       Retrieves the current timer count via BIOS call. For use when      *
  512. *       timing copies. The timer ticks 18.2 times per second. The value    *
  513. *       returned by this function has a jitter of -0,+(1/18.2) seconds.    *
  514. *                                                                          *
  515. *   ENTRY:                                                                 *
  516. *                                                                          *
  517. *       Void.                                                              *
  518. *                                                                          *
  519. *   EXIT:                                                                  *
  520. *                                                                          *
  521. *       Returns the timer count.                                           *
  522. *                                                                          *
  523. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  524. *                                                                          *
  525. ***************************************************************************/
  526. unsigned long get_tick(void)
  527. {
  528.     unsigned long retval;
  529.  
  530. #ifdef INLINE_ASM
  531.     ASM  push     cx                            /* push register values     */
  532.     ASM  push     dx
  533.     ASM  xor      ah, ah                        /* AH = 00h, get count call */
  534.     ASM  int      1Ah                           /* make call                */
  535.     ASM  mov      WORD PTR [retval + 2], cx     /* save returned value      */
  536.     ASM  mov      WORD PTR [retval], dx
  537.     ASM  pop      dx
  538.     ASM  pop      cx
  539. #else
  540.     union REGS r;
  541.  
  542.     /* do the same thing in C */
  543.     r.h.ah = 0x0;
  544.     int86(0x1A, &r, &r);
  545.     retval = r.x.cx;
  546.     retval <<= 16;
  547.     retval |= r.x.dx;
  548. #endif
  549.  
  550.     return retval;
  551. } /* end of get_tick() */
  552.  
  553.  
  554. /***************************************************************************
  555. *   FUNCTION: NORMPTR                                                      *
  556. *                                                                          *
  557. *   DESCRIPTION:                                                           *
  558. *                                                                          *
  559. *       Normalizes a far pointer -- reduces the offset to the smallest     *
  560. *       possible value (somewhere between 0 and 0xF) by adding to the      *
  561. *       segment.                                                           *
  562. *                                                                          *
  563. *   ENTRY:                                                                 *
  564. *                                                                          *
  565. *       norm - pointer to be normalized                                    *
  566. *                                                                          *
  567. *   EXIT:                                                                  *
  568. *                                                                          *
  569. *       Returns normalized pointer.                                        *
  570. *                                                                          *
  571. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  572. *                                                                          *
  573. ***************************************************************************/
  574. unsigned char huge *normptr(unsigned char far *norm)
  575. {
  576.     unsigned char huge *retval = (unsigned char huge *) norm;
  577.  
  578. #ifdef INLINE_ASM
  579.     ASM  push     cx                        /* preserve register values */
  580.     ASM  push     di
  581.     ASM  push     si
  582.     ASM  mov      si, WORD PTR [retval]     /* load offset into SI          */
  583.     ASM  mov      di, si                    /* load offset into DI too      */
  584.     ASM  mov      cl, 4                     /* load 4 into CL               */
  585.     ASM  shr      di, cl                    /* shift DI right by 4, which   */
  586.                                             /* converts it to a segment     */
  587.     ASM  add      WORD PTR [retval + 2], di /* add to segment in pointer    */
  588.     ASM  and      si, 0Fh                   /* zero all but lowest nibble   */
  589.                                             /* of offset                    */
  590.     ASM  mov      WORD PTR [retval], si     /* put offset back in pointer   */
  591.     ASM  pop      si                        /* restore register values      */
  592.     ASM  pop      di
  593.     ASM  pop      cx
  594. #else
  595.     unsigned int segment, offset;
  596.  
  597.     /* do the same thing in C -- extract segment and offset from pointer */
  598.     segment = FP_SEG(retval);
  599.     offset = FP_OFF(retval);
  600.     /* add high three nibbles of offset to segment */
  601.     segment += (offset >> 4);
  602.     /* preseve only lowest nibble of offset */
  603.     offset &= 0xF;
  604.     /* reconstruct pointer from modified segment and offset */
  605.     retval = MK_FP(segment, offset);
  606. #endif
  607.  
  608.     return retval;
  609. } /* end of normptr() */
  610.  
  611.  
  612. /*
  613. ** The following group of functions is the same in spirit as the preceding
  614. ** group, but equivalents already exist in the libraries of some compilers.
  615. ** These functions are only used if the symbol NO_FFUNC is defined, which
  616. ** should only be done when the compiler's library does not already contain
  617. ** equivalent functions.
  618. */
  619.  
  620. /***************************************************************************
  621. *   FUNCTION: FMEMCMP                                                      *
  622. *                                                                          *
  623. *   DESCRIPTION:                                                           *
  624. *                                                                          *
  625. *       A replacement _fmemcmp() function for compilers which do not have  *
  626. *       it in their libraries. Compares two regions of memory.             *
  627. *                                                                          *
  628. *   ENTRY:                                                                 *
  629. *                                                                          *
  630. *       buf1 - pointer to first region                                     *
  631. *       buf2 - pointer to second region                                    *
  632. *       n    - length of regions                                           *
  633. *                                                                          *
  634. *   EXIT:                                                                  *
  635. *                                                                          *
  636. *       Returns 0 on match, negative if mismatch byte in buf1 is less than *
  637. *       corresponding byte in buf2, positive if vice versa.                *
  638. *                                                                          *
  639. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  640. *                                                                          *
  641. ***************************************************************************/
  642. int Fmemcmp(void far *buf1, void far *buf2, unsigned int n)
  643. {
  644.     unsigned char huge *temp1, huge *temp2;
  645.     int retval = 0;
  646. #ifndef INLINE_ASM
  647.     int loop;
  648. #endif
  649.  
  650.     /* normalize pointers */
  651.     temp1 = normptr((unsigned char far *) buf1);
  652.     temp2 = normptr((unsigned char far *) buf2);
  653.  
  654. #ifdef INLINE_ASM
  655.     ASM  push     cx                    /* preserve register values     */
  656.     ASM  push     di
  657.     ASM  push     si
  658.     ASM  push     ds
  659.     ASM  push     es
  660.     ASM  lds      si, [temp1]           /* load first pointer in DS:SI  */
  661.     ASM  les      di, [temp2]           /* load second pointer in ES:DI */
  662.     ASM  mov      cx, [n]               /* load length in CX            */
  663.     ASM  repz     cmpsb                 /* compare while equal          */
  664.     ASM  jcxz     alldone               /* if CX is 0, all were equal   */
  665.     ASM  ja       higher                /* not equal, set return value  */
  666.     ASM  mov      WORD PTR [retval], -1
  667.     ASM  jmp      alldone
  668. higher:
  669.     ASM  mov      WORD PTR [retval], 1
  670. alldone:
  671.     ASM  pop      es                    /* restore register values      */
  672.     ASM  pop      ds
  673.     ASM  pop      si
  674.     ASM  pop      di
  675.     ASM  pop      cx
  676. #else
  677.     /* do the same thing in C */
  678.     for (loop = 0; loop < n; loop++, temp1++, temp2++)
  679.     {
  680.         if (*temp1 == *temp2)
  681.         {
  682.             continue;
  683.         }
  684.         retval = (int) (*temp1 - *temp2);
  685.         break;
  686.     }
  687. #endif
  688.  
  689.     return retval;
  690. } /* end of Fmemcmp() */
  691.  
  692.  
  693. /***************************************************************************
  694. *   FUNCTION: FMEMSET                                                      *
  695. *                                                                          *
  696. *   DESCRIPTION:                                                           *
  697. *                                                                          *
  698. *       A replacement _fmemset() function for compilers which do not have  *
  699. *       it in their libraries. Sets a region of memory to a particular     *
  700. *       value.                                                             *
  701. *                                                                          *
  702. *   ENTRY:                                                                 *
  703. *                                                                          *
  704. *       s - pointer to region of memory                                    *
  705. *       c - byte value to set memory to                                    *
  706. *       n - length of region                                               *
  707. *                                                                          *
  708. *   EXIT:                                                                  *
  709. *                                                                          *
  710. *       Returns s.                                                         *
  711. *                                                                          *
  712. *   CONSTRAINTS/SIDE EFFECTS:                                              *
  713. *                                                                          *
  714. ***************************************************************************/
  715. void Fmemset(void far *s, int c, unsigned int n)
  716. {
  717.     unsigned char huge *temp;
  718.  
  719.     /* normalize pointer */
  720.     temp = normptr((unsigned char far *) s);
  721.  
  722. #ifdef INLINE_ASM
  723.     /* if length is odd, use slower way */
  724.     if ((n % 2) == 1)
  725.     {
  726.         ASM  push     ax                /* preserve register values     */
  727.         ASM  push     cx
  728.         ASM  push     di
  729.         ASM  push     es
  730.         ASM  les      di, [temp]        /* load pointer into ES:DI      */
  731.         ASM  mov      al, BYTE PTR [c]  /* load value into AL           */
  732.         ASM  mov      cx, [n]           /* load length into CX          */
  733.         ASM  rep      stosb             /* store value in memory        */
  734.         ASM  pop      es                /* restore register values      */
  735.         ASM  pop      di
  736.         ASM  pop      cx
  737.         ASM  pop      ax
  738.     }
  739.     else
  740.     {
  741.         /* otherwise use faster way, storing entire words at once */
  742.         /* convert length in bytes to length in words */
  743.         n /= 2;
  744.         ASM  push     ax                /* preserve register values         */
  745.         ASM  push     cx
  746.         ASM  push     di
  747.         ASM  push     es
  748.         ASM  les      di, [temp]        /* load pointer into ES:DI          */
  749.         ASM  mov      al, BYTE PTR [c]  /* load value into AL               */
  750.         ASM  mov      ah, al            /* load value into AH too           */
  751.         ASM  mov      cx, [n]           /* load length into CX              */
  752.         ASM  rep      stosw             /* store value in memory by words   */
  753.         ASM  pop      es                /* restore register values          */
  754.         ASM  pop      di
  755.         ASM  pop      cx
  756.         ASM  pop      ax
  757.     }
  758. #else
  759.     /* do the same thing in C */
  760.     for (; n; n--, temp++)
  761.     {
  762.         *temp = c;
  763.     }
  764. #endif
  765.  
  766.     return;
  767. } /* end of Fmemset() */
  768.  
  769.